Load data


In [1]:
data_dir = r'C:\Data\Antonio\Philip\081114Patch clamp\nanorods 630\fov2 - good\122055_take2 100Hz\\'

In [2]:
from __future__ import division
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_context(rc={'lines.markeredgewidth': 1})  # workaround for a bug in matplotlib 1.4.2

In [3]:
from patchclamp import PatchDataset

In [4]:
data = PatchDataset(data_dir)

The attributes data.voltage/current/time are resampled at the camera frame rate:


In [5]:
plt.plot(data.time[:100], data.voltage[:100], label='Voltage')
plt.ylabel('Voltage (V)')
plt.twinx()
plt.plot(data.time[:100], data.current[:100], label='Current',
         color=sns.color_palette()[1])
plt.ylabel('Current (pA)')
plt.grid(False)
plt.xlabel('Time (s)')


Out[5]:
<matplotlib.text.Text at 0x187720f0>

In [6]:
sns.set_style('dark')

In [7]:
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(data.video.mean(0), cmap='cubehelix')
plt.colorbar(im);
ax.set_title('Mean frame')


Out[7]:
<matplotlib.text.Text at 0x187811d0>

Background subtraction

The background is computed as a 3-D low-pass Gaussian filter:


In [8]:
import scipy.ndimage as ndi

In [9]:
mvideo = data.video.mean(0)

In [10]:
data.video.shape, data.video.dtype


Out[10]:
((1996L, 192L, 272L), dtype('uint16'))

In [11]:
smooth_mvideo = ndi.gaussian_filter(mvideo, sigma=20)
smooth_mvideo.shape, smooth_mvideo.dtype


Out[11]:
((192L, 272L), dtype('float64'))

In [12]:
smooth_frame = ndi.gaussian_filter(data.video[0].astype('float64'), sigma=20)
smooth_frame.shape, smooth_frame.dtype


Out[12]:
((192L, 272L), dtype('float64'))

In [13]:
smooth_video = ndi.gaussian_filter(data.video.astype('float64'), sigma=20)
smooth_video.shape, smooth_video.dtype


Out[13]:
((1996L, 192L, 272L), dtype('float64'))

In [14]:
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(smooth_mvideo, cmap='cubehelix', vmin=104, vmax=109)
plt.colorbar(im);
ax.set_title('Mean background frame');



In [15]:
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(smooth_frame, cmap='cubehelix', vmin=104, vmax=109)
plt.colorbar(im);
ax.set_title('Background frame 0');



In [16]:
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(smooth_video.mean(0), cmap='cubehelix', vmin=104, vmax=109)
plt.colorbar(im);



In [17]:
corr_video = data.video.astype(np.float64) - smooth_video
corr_video.shape, corr_video.dtype


Out[17]:
((1996L, 192L, 272L), dtype('float64'))

In [18]:
nframe = 5
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(corr_video[nframe], cmap='cubehelix', vmin=-50, vmax=60)
plt.colorbar(im);
ax.set_title('Background-corrected frame %d' % nframe);


Select QD positions


In [20]:
%matplotlib qt

In [21]:
from figscroller import FrameScroller

Explore the video frame by frame:


In [22]:
fig, ax = plt.subplots(figsize=(14, 9))
im = ax.imshow(corr_video[0], cmap='cubehelix')
plt.colorbar(im)
scroller = FrameScroller(fig, im, corr_video)
points = plt.ginput(10, timeout=0)
points


C:\Users\laser2002j\Anaconda\lib\site-packages\matplotlib\backend_bases.py:2382: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str, mplDeprecation)
Out[22]:
[(116.22811059907835, 113.91013824884794),
 (127.58755760368663, 62.988479262672854),
 (171.45852534562212, 104.50921658986178),
 (102.12672811059909, 116.26036866359449),
 (100.55990783410138, 100.20046082949312),
 (165.9746543778802, 99.41705069124427),
 (164.01612903225808, 109.99308755760372),
 (156.18202764976959, 126.44470046082951),
 (151.87327188940094, 136.62903225806451),
 (151.87327188940094, 149.16359447004609)]

Or use only the mean frame:


In [12]:
#frame = corr_video.mean(0)
frame = data.video.mean(0)

fig, ax = plt.subplots(figsize=(14, 9))
im = ax.imshow(frame, cmap='cubehelix')
plt.colorbar(im)
points = plt.ginput(10, timeout=0)
points


Out[12]:
[(161.04569892473114, 109.89516129032256),
 (163.78763440860212, 112.40860215053762),
 (226.39516129032253, 41.118279569892479),
 (246.95967741935479, 133.6586021505376),
 (26.233870967741929, 140.0564516129032),
 (103.92204301075265, 48.887096774193537),
 (16.86559139784945, 58.712365591397855),
 (102.32258064516125, 3.6451612903225907),
 (104.15053763440858, 163.13440860215053),
 (185.95161290322577, 148.96774193548384)]

QD on patched cell:


In [19]:
points_patched = \
    [(92.954301075268802, 122.91935483870967),
     (93.411290322580612, 127.26075268817203),
     (91.81182795698922, 132.05913978494624),
     (128.14247311827953, 136.17204301075267),
     (129.28494623655911, 135.02956989247309),
     (139.1102150537634, 125.2043010752688),
     (147.10752688172039, 66.938172043010752),
     (101.4086021505376, 88.188172043010752),
     (100.72311827956986, 89.787634408602145),
     (154.64784946236554, 95.956989247311824)]

QD unpatched:


In [20]:
points_unpatched = \
    [(161.04569892473114, 109.89516129032256),
     (163.78763440860212, 112.40860215053762),
     (226.39516129032253, 41.118279569892479),
     (246.95967741935479, 133.6586021505376),
     (26.233870967741929, 140.0564516129032),
     (103.92204301075265, 48.887096774193537),
     (16.86559139784945, 58.712365591397855),
     (102.32258064516125, 3.6451612903225907),
     (104.15053763440858, 163.13440860215053),
     (185.95161290322577, 148.96774193548384)]

In [21]:
%matplotlib inline

In [22]:
sns.set_style('dark')

In [23]:
fig, ax = plt.subplots(figsize=(10, 6))
for point in points_patched:
    plt.plot(point[0], point[1], 'r+')
im = ax.imshow(data.video.mean(0), cmap='cubehelix')
plt.colorbar(im);
ax.set_title('QD on patched cell')

fig, ax = plt.subplots(figsize=(10, 6))
for point in points_unpatched:
    plt.plot(point[0], point[1], 'r+')
im = ax.imshow(data.video.mean(0), cmap='cubehelix')
plt.colorbar(im);
ax.set_title('Unpatched QD');


Timetraces

Timetrace can be extracted by averaging a square or a circle of pixels:


In [24]:
def get_square_mask(point, pad=2):
    row, col = point
    mask = (slice(None), slice(row-pad, row+pad+1), slice(col-pad, col+pad+1))
    return mask

def get_timetrace_square(video, point, pad=2):
    mask = get_square_mask(point, pad)
    timetrace = video[mask].mean(1).mean(1)
    return timetrace

In [25]:
def get_round_mask(point, clip_radius, shape2d):
    row, col = point
    X, Y = np.mgrid[-clip_radius-1: clip_radius+2, -clip_radius-1: clip_radius+2]
    R = np.sqrt(X**2 + Y**2)
    local_mask = R <= clip_radius + 0.5
    bmask = np.zeros(shape2d, dtype=bool)
    bmask[-clip_radius-1+row: clip_radius+2+row, -clip_radius-1+col: clip_radius+2+col] = local_mask
    imask = np.nonzero(bmask)
    return imask

def get_timetrace_circle(video, point, clip_radius=2):
    imask = get_round_mask(point, clip_radius, video.shape[1:])
    timetrace = np.zeros(video.shape[0])
    for i in range(timetrace.size):
        timetrace[i] = video[i, imask[0], imask[1]].mean()
    return timetrace

In [26]:
sns.set_style('darkgrid')

In [27]:
video = corr_video
pad = 2
clip_radius = 2
vert_offset = 8

In [28]:
fig, ax = plt.subplots(1, 1, figsize=(18, 4), sharex=True)
timetrace1 = get_timetrace_circle(data.video, points_patched[0], clip_radius=clip_radius)
timetrace2 = get_timetrace_circle(corr_video, points_patched[0], clip_radius=clip_radius)
ax.plot(data.time, timetrace1 - timetrace2 - 100, label='QD (%.1f, %.1f)' % point);
ax.set_title('Difference between background corrected and raw timetrace');



In [29]:
%matplotlib inline

In [30]:
fig, ax = plt.subplots(1, 1, figsize=(16, 1*len(points_patched)), sharex=True)
fig.subplots_adjust(left=0.04, right=0.96, hspace=0)
for i, point in enumerate(points_patched):
    timetrace = get_timetrace_circle(video, point, clip_radius=clip_radius)
    ax.plot(data.time, timetrace + vert_offset*i, label='QD (%.1f, %.1f)' % point);
ax.set_xlim(0, 1)
plt.legend(ncol=5)


Out[30]:
<matplotlib.legend.Legend at 0x1aedadd8>

In [54]:
%matplotlib qt

In [55]:
from figscroller import HorizontalScroller

In [56]:
fig, ax = plt.subplots(1, 1, figsize=(20, 1*len(points_patched)), sharex=True)
fig.subplots_adjust(left=0.04, right=0.96, hspace=0)
for i, point in enumerate(points_patched):
    timetrace = get_timetrace_circle(video, point, clip_radius=clip_radius)
    ax.plot(data.time, timetrace + vert_offset*i, label='QD (%.1f, %.1f)' % point)
plt.legend(ncol=5)
HorizontalScroller(fig)


Out[56]:
<figscroller.HorizontalScroller at 0x2fff5ac8>

In [79]:
%matplotlib inline

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: